home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /***************************************************************************
- *
- * @(#) - BZ - Multiplayer tank game - Sound support.
- *
- * $Id: bzsound.c,v 1.4 1993/08/11 19:46:39 adele Exp $
- *
- * Chris Fouts - Silicon Graphics, Inc.
- * October, 1991
- **************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/prctl.h>
- #include <string.h>
- #include <signal.h>
- #include <malloc.h>
- #include <unistd.h>
- #include <audio.h>
- #include <invent.h>
- #include <math.h>
-
- #include "aiff.h"
- #include "bzsound.h"
-
- #define ABS(x) ( ( (x) < 0 ) ? -(x) : (x) )
-
- static char *version_id = "$Id: bzsound.c,v 1.4 1993/08/11 19:46:39 adele Exp $" ;
-
-
- typedef union
- {
- unsigned char b[2];
- short s;
- } align_short_t;
-
- typedef union
- {
- unsigned char b[4];
- long l;
- } align_long_t;
-
-
- #define MAX_EXP_DEPTH 5
- #define MAX_EXP_ANGLE 3
- #define EXP_DELTA_ANGLE ( M_PI / 4.0 )
- #define EXP_DELTA_DEPTH 250.0
- #define MAX_AUDIO_PORTS 3
-
- extern char *basename ;
- static unsigned long orig_left_gain ;
- static unsigned long orig_right_gain ;
- static unsigned long orig_output_rate ;
- static unsigned long curr_left_gain ;
- static unsigned long curr_right_gain ;
- static long sound_size[SFX_N_SOUNDS] ;
- static short *sound_data[SFX_N_SOUNDS] ;
- static char *sound_file[SFX_N_SOUNDS] = {
- "mine_drop.aiff",
- "mine_pick_up.aiff",
- "explosion.aiff",
- "fire.aiff",
- "bump.aiff",
- "pop.aiff",
- "flag_grabbed.aiff",
- "flag_won.aiff",
- "flag_lost.aiff",
- "pause.aiff",
- } ;
- static long explosion_size ;
- static short *explosion_data[MAX_EXP_DEPTH][MAX_EXP_ANGLE] ;
- static short *new_sound_data ;
- static long new_sound_size ;
- static int new_sound = 0 ;
- static char *filename; /* input file name */
- static int bytes_per_samp; /* sample width */
- static int samps_per_frame; /* frame size */
- static int frames_per_sec; /* sample rate */
- static ALport audio_port[MAX_AUDIO_PORTS+1] ;/* foreground audio ports */
- static int sound_child = 0 ;
- static int sound_enabled = 0 ;
- static int has_sound_hw = 0 ;
-
-
- static unsigned long gain_settings[] =
- { 0, 2, 3, 5, 9, 16, 29, 50, 91, 156, 255 } ;
- static int gain_index ;
-
- int pause( void ) ;
- /* BEGIN PROTOTYPES -S bzsound.c */
- static int check_for_audio_hw( void ) ;
- static double ConvertFromIeeeExtended( char *bytes ) ;
- static char *init_audio( int fd, audio_params_t *audio_params,
- ssnd_chunk_t *ssnd_data, comm_chunk_t *comm_data,
- long *size ) ;
- static ALport init_audio_port( int all ) ;
- static void init_explosion_data( short *src_data, long src_size ) ;
- static char *load_aiff_file( char *dir, char *name, long *size ) ;
- static char *read_aiff_file( int fd, long *size ) ;
- static int read_chunk_header( int fd, chunk_header_t *chunk_header ) ;
- static void read_comm_chunk( int fd, comm_chunk_t *comm_data,
- audio_params_t *audio_params ) ;
- static void read_form_chunk( int fd, chunk_header_t *chunk_header ) ;
- static void read_ssnd_chunk( int fd, chunk_header_t *chunk_header,
- ssnd_chunk_t *ssnd_data ) ;
- static void reset_audio_hw( void ) ;
- static void set_gain( float l, float r ) ;
- static void set_gain_index( unsigned long gain ) ;
- static void signal_sound( short *data, long size ) ;
- static void skip_chunk( int fd, chunk_header_t *chunk_header ) ;
- static void sound_handler( void *arg ) ;
- static void wake_up( int sig, int code, struct sigcontext *sc ) ;
- /* END PROTOTYPES -S bzsound.c */
-
-
- int init_sound( void )
- {
- int i ;
- char *audio_dir ;
-
- if( ( has_sound_hw = check_for_audio_hw() ) != 0 ) {
- if( ( audio_port[0] = init_audio_port( 1 ) ) == NULL ) {
- fprintf( stderr, "%s: no audio ports available\n", basename ) ;
- return( 1 ) ;
- }
-
- if( ( audio_port[1] = init_audio_port( 0 ) ) != NULL ) {
- audio_port[2] = init_audio_port( 0 ) ;
- }
- audio_port[3] = NULL ;
-
- if( ( audio_dir = getenv( "BZ_AUDIO_DIR" ) ) == NULL &&
- ( audio_dir = getenv( "BZ_DIR" ) ) == NULL ) {
- audio_dir = DATA_DIR ;
- }
-
- for( i = 0 ; i < SFX_N_SOUNDS ; i++ ) {
- sound_data[i] = (short *)load_aiff_file( audio_dir, sound_file[i],
- &sound_size[i] ) ;
- }
-
- if( sound_data[SFX_EXPLOSION] ) {
- init_explosion_data( sound_data[SFX_EXPLOSION],
- sound_size[SFX_EXPLOSION] ) ;
- }
- else {
- explosion_size = 0 ;
- }
-
- if( ( sound_child = sproc( sound_handler, PR_SALL, audio_port ) ) < 0 ){
- fprintf( stderr, "%s: could not sproc sound handler: %s\n",
- basename, strerror( errno ) ) ;
- return( 1 ) ;
- }
- else {
- sound_enabled = 1 ;
- }
- }
- else {
- explosion_size = 0 ;
- sound_enabled = 0 ;
- return( 1 ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- void set_volume(
- int level
- )
- {
- if( level >= 0 &&
- level < sizeof( gain_settings ) / sizeof( gain_settings[0] ) ) {
- gain_index = level ;
- curr_left_gain = curr_right_gain = gain_settings[gain_index] ;
- }
- }
-
-
-
- int toggle_sound( void )
- {
- if( has_sound_hw && sound_child )
- sound_enabled = !sound_enabled ;
-
- return( sound_enabled ) ;
- }
-
-
-
- void end_sound( void )
- {
- if( sound_child > 0 ) {
- kill( sound_child, SIGKILL ) ;
- }
- if( has_sound_hw )
- reset_audio_hw() ;
- }
-
-
-
- static void wake_up(
- int sig,
- int code,
- struct sigcontext *sc
- )
- {
- }
-
-
-
- static void reset_audio_hw( void )
- {
- long pvbuf[6] ;
- long buflen ;
-
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[1] = orig_left_gain ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[3] = orig_right_gain ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- pvbuf[5] = orig_output_rate ;
- buflen = 6 ;
-
- ALsetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- }
-
-
-
- static void set_gain(
- float l,
- float r
- )
- {
- long pvbuf[6] ;
- long buflen ;
-
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[1] = l * curr_left_gain ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[3] = r * curr_right_gain ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- pvbuf[5] = AL_RATE_16000 ;
- buflen = 6 ;
-
- ALsetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- }
-
-
-
- static void sound_handler(
- void *arg
- )
- {
- ALport *ap = (ALport *)arg ;
- int i ;
- int empty ;
- int next_port = 0 ;
- int n_audio_ports ;
- long max_samps_per_frame ;
- long samps_to_play[MAX_AUDIO_PORTS] ;
- long samps_played[MAX_AUDIO_PORTS] ;
- short *sample[MAX_AUDIO_PORTS] ;
- struct sigaction act ;
-
- prctl( PR_TERMCHILD, 0 ) ;
-
- max_samps_per_frame = 0.1 * 16000. ;
-
- n_audio_ports = 0 ;
- while( ap[n_audio_ports] != NULL ) {
- sample[n_audio_ports] = 0 ;
- samps_to_play[n_audio_ports] = 0 ;
- n_audio_ports++ ;
- }
-
- act.sa_handler = wake_up ;
- sigemptyset( &(act.sa_mask) ) ;
- act.sa_flags = 0 ;
- sigaction( SIGUSR1, &act, NULL ) ;
-
- while( 1 ) {
- if( new_sound ) {
- sample[next_port] = new_sound_data ;
- samps_to_play[next_port] = new_sound_size ;
- samps_played[next_port] = 0 ;
- new_sound = 0 ;
- next_port = ( next_port + 1 ) % n_audio_ports ;
- }
- empty = 0 ;
- for( i = 0 ; i < n_audio_ports ; i++ ) {
- if( samps_to_play[i] > max_samps_per_frame ) {
- set_gain( 1., 1. ) ;
- ALwritesamps( ap[i], sample[i] + samps_played[i],
- max_samps_per_frame ) ;
- samps_played[i] += max_samps_per_frame ;
- samps_to_play[i] -= max_samps_per_frame ;
- empty = 1 ;
- }
- else if( samps_to_play[i] > 0 ) {
- set_gain( 1., 1. ) ;
- ALwritesamps( ap[i], sample[i] + samps_played[i],
- samps_to_play[i] ) ;
- samps_to_play[i] = 0 ;
- }
- }
- if( empty == 0 ) {
- pause() ;
- }
- }
- }
-
-
-
- void sfx(
- int sound
- )
- {
- if( audio_port[0] && sound_data[sound] && sound_enabled ) {
- signal_sound( sound_data[sound], sound_size[sound] ) ;
- }
- }
-
-
-
- void explosion_sfx(
- float x,
- float y,
- float heading
- )
- {
- int d ;
- int a ;
- int offset = 0 ;
- double angle ;
-
- if( explosion_size && sound_enabled ) {
- d = sqrt( x * x + y * y ) / EXP_DELTA_DEPTH ;
- if( d > MAX_EXP_DEPTH - 1 )
- d = MAX_EXP_DEPTH - 1 ;
- angle = atan2( y, x ) + heading * ( M_PI / 180.0 ) ;
- if( angle > 2.* M_PI )
- angle -= 2. * M_PI ;
- if( angle < 0.0 )
- angle = -angle ;
- if( angle > M_PI ) {
- angle = 2. * M_PI - angle ;
- }
- if( angle > M_PI_2 ) {
- angle = M_PI - angle ;
- offset = 1 ;
- }
- a = ( angle + 0.5 * EXP_DELTA_ANGLE ) / EXP_DELTA_ANGLE ;
- signal_sound( explosion_data[d][a] + offset, explosion_size ) ;
- }
- }
-
-
-
- static void signal_sound(
- short *data,
- long size
- )
- {
- if( sound_child ) {
- new_sound_data = data ;
- new_sound_size = size ;
- new_sound = 1 ;
- kill( sound_child, SIGUSR1 ) ;
- }
- }
-
-
-
- static ALport init_audio_port(
- int all
- )
- {
- long pvbuf[6] ;
- long buflen ;
- ALconfig audio_port_config;
- ALport ap ;
-
- if( all ) {
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- buflen = 6 ;
- ALgetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- curr_left_gain = orig_left_gain = pvbuf[1] ;
- curr_right_gain = orig_right_gain = pvbuf[3] ;
- orig_output_rate = pvbuf[5] ;
-
- set_gain_index( ( orig_left_gain + orig_right_gain ) / 2 ) ;
- }
-
- /*
- * configure and open audio port
- */
- audio_port_config = ALnewconfig();
- ALsetwidth( audio_port_config, AL_SAMPLE_16 ) ;
- ALsetchannels( audio_port_config, AL_STEREO ) ;
-
- /*
- * make the ring buffer large enough to hold 0.1 sec of audio samples
- */
- ALsetqueuesize( audio_port_config, 16000 * 0.1 ) ;
- ap = ALopenport( basename, "w", audio_port_config ) ;
-
- ALfreeconfig( audio_port_config ) ;
-
- return( ap ) ;
- }
-
-
-
- static char *load_aiff_file(
- char *dir,
- char *name,
- long *size
- )
- {
- int fd ;
- char *data ;
-
- filename = malloc( strlen( name ) + strlen( dir ) + 2 ) ;
- sprintf( filename, "%s/%s", dir, name ) ;
-
- if( ( fd = open( filename, O_RDONLY ) ) < 0 ) {
- fprintf( stderr, "%s: can't open %s: %s\n", basename, filename,
- strerror( errno ) ) ;
- free( filename ) ;
- return( NULL ) ;
- }
-
- data = read_aiff_file( fd, size ) ;
-
- free( filename ) ;
-
- close( fd ) ;
-
- return( data ) ;
- }
-
-
-
- static char *read_aiff_file(
- int fd,
- long *size
- )
- {
- int n ;
- chunk_header_t chunk_header ;
- comm_chunk_t comm_data ;
- ssnd_chunk_t ssnd_data ;
- audio_params_t audio_params ;
-
- if( ( n = read_chunk_header( fd, &chunk_header ) ) != CHUNK_HEADER ) {
- fprintf( stderr, "%s: failed to read FORM chunk header\n", basename ) ;
- return( NULL ) ;
- }
-
- if( strncmp( chunk_header.id, "FORM", 4 ) ) {
- fprintf( stderr, "%s: couldn't find FORM chunk id\n", basename ) ;
- return( NULL ) ;
- }
-
- read_form_chunk( fd, &chunk_header ) ;
-
- /*
- * loop on the local chunks
- */
- while( ( n = read_chunk_header( fd, &chunk_header ) ) != 0 ) {
- if( n != CHUNK_HEADER ) {
- fprintf( stderr, "%s: failed to read a chunk header\n", basename ) ;
- return( NULL ) ;
- }
-
- /* common */
- if( !strncmp( chunk_header.id, "COMM", 4 ) ) {
- read_comm_chunk( fd, &comm_data, &audio_params ) ;
- }
- /* sound data */
- else if( !strncmp( chunk_header.id, "SSND", 4 ) ) {
- read_ssnd_chunk( fd, &chunk_header, &ssnd_data ) ;
- }
- else if( ( !strncmp( chunk_header.id, "MARK", 4 ) ) /* marker */
- || ( !strncmp( chunk_header.id, "INST", 4 ) ) /* instrument */
- || ( !strncmp( chunk_header.id, "APPL", 4 ) ) /* appl specific */
- || ( !strncmp( chunk_header.id, "MIDI", 4 ) ) /* midi data */
- || ( !strncmp( chunk_header.id, "AESD", 4 ) ) /* audio rec */
- || ( !strncmp( chunk_header.id, "COMT", 4 ) ) /* comments */
- || ( !strncmp( chunk_header.id, "NAME", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "AUTH", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "(c) ", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "ANNO", 4 ) ) /* text */
- ) {
- skip_chunk( fd, &chunk_header ) ;
- }
- else {
- fprintf( stderr, "%s: bad chunk id 0x%02x%02x%02x%02x\n",
- basename, chunk_header.id[0],chunk_header.id[1],
- chunk_header.id[2], chunk_header.id[3]);
- }
- } /* while */
-
- return( init_audio( fd, &audio_params, &ssnd_data, &comm_data, size ) ) ;
- }
-
-
-
- /*
- * R E A D _ C H U N K _ H E A D E R
- */
- static int read_chunk_header(
- int fd,
- chunk_header_t *chunk_header
- )
- {
- align_long_t align_long ;
- char buf[CHUNK_HEADER] ;
- int i ;
- int n ;
-
- if( ( n = read( fd, buf, CHUNK_HEADER) ) != CHUNK_HEADER ) {
- return( n ) ;
- }
-
- for( i = 0 ; i < 4 ; i++ ) {
- chunk_header->id[i] = buf[i] ;
- }
-
- for( i = 0 ; i < 4 ; i++ ) {
- align_long.b[i] = buf[i+4] ;
- }
- chunk_header->size = align_long.l ;
-
- return( CHUNK_HEADER ) ;
- }
-
-
-
-
- static void read_form_chunk(
- int fd,
- chunk_header_t *chunk_header
- )
- {
- char buf[FORM_CHUNK_DATA];
-
- if( chunk_header->size < 0 ) {
- fprintf( stderr, "%s: invalid FORM chunk data size %ld\n", basename,
- chunk_header->size ) ;
- exit( 1 ) ;
- }
- else if( chunk_header->size == 0 ) {
- fprintf( stderr, "%s: FORM chunk data size = 0\n", basename ) ;
- exit( 0 ) ;
- }
-
- if( read( fd, buf, FORM_CHUNK_DATA ) != FORM_CHUNK_DATA ) {
- fprintf( stderr, "%s: couldn't read AIFF identifier from %s\n",
- basename, filename ) ;
- exit( 1 ) ;
- }
- if( strncmp( buf, "AIFF", 4 ) ) {
- fprintf( stderr, "%s: %s does not have an AIFF identifier\n",
- basename, filename ) ;
- exit(1);
- }
- }
-
-
-
- /*
- * R E A D _ C O M M _ C H U N K
- */
- static void read_comm_chunk(
- int fd,
- comm_chunk_t *comm_data,
- audio_params_t *audio_params
- )
- {
- int n;
- char *buf, *bufp;
- int i;
- align_short_t align_short;
- align_long_t align_long;
- double tmpdouble;
-
- buf = malloc(COMM_CHUNK_DATA + 1); /* leave an extra loc at the end */
-
- if ((n = read(fd, buf, COMM_CHUNK_DATA)) != COMM_CHUNK_DATA)
- {
- fprintf(stderr,
- "%s: failed to read COMM chunk data. Expected %d bytes, got %d.\n",
- basename, COMM_CHUNK_DATA, n);
- exit(1);
- }
- bufp = buf;
- for (i=0; i<2; i++)
- {
- align_short.b[i] = *bufp++;
- }
- comm_data->nchannels = align_short.s;
- for (i=0; i<4; i++)
- {
- align_long.b[i] = *bufp++;
- }
- comm_data->nsampframes = align_long.l;
- for (i=0; i<2; i++)
- {
- align_short.b[i] = *bufp++;
- }
- comm_data->sampwidth = align_short.s;
-
- /*
- * the sample rate value from the common chunk is an 80-bit IEEE extended
- * floating point number:
- * [s bit] [15 exp bits (bias=16383)] [64 mant bits (leading 1 not hidden)]
- *
- */
- tmpdouble = ConvertFromIeeeExtended(bufp);
- bufp+=10;
- comm_data->samprate = (long)tmpdouble;
-
- switch (comm_data->samprate)
- {
- case 48000:
- audio_params->samprate = AL_RATE_48000;
- break;
- case 44100:
- audio_params->samprate = AL_RATE_44100;
- break;
- case 32000:
- audio_params->samprate = AL_RATE_32000;
- break;
- case 22050:
- audio_params->samprate = AL_RATE_22050;
- break;
- case 16000:
- audio_params->samprate = AL_RATE_16000;
- break;
- case 11025:
- audio_params->samprate = AL_RATE_11025;
- break;
- case 8000:
- audio_params->samprate = AL_RATE_8000;
- break;
- default:
- fprintf(stderr,"%s: can't set output sample rate to %ld\n",
- basename, comm_data->samprate);
- audio_params->samprate = AL_RATE_48000;
- }
-
- switch (comm_data->nchannels)
- {
- case 1:
- audio_params->nchannels = AL_MONO;
- break;
- case 2:
- audio_params->nchannels = AL_STEREO;
- break;
- default:
- fprintf(stderr, "%s: can't handle %d channels per frame\n",
- basename, comm_data->nchannels);
- audio_params->nchannels = AL_STEREO;
- }
- switch (comm_data->sampwidth)
- {
- case 8:
- audio_params->sampwidth = AL_SAMPLE_8;
- break;
- case 16:
- audio_params->sampwidth = AL_SAMPLE_16;
- break;
- case 24:
- audio_params->sampwidth = AL_SAMPLE_24;
- break;
- default:
- fprintf(stderr, "%s: unsupported sample width %d bits\n",
- basename, comm_data->nchannels);
- audio_params->sampwidth = AL_SAMPLE_16;
- }
- free(buf);
- }
-
-
-
- static void read_ssnd_chunk(
- int fd,
- chunk_header_t *chunk_header,
- ssnd_chunk_t *ssnd_data
- )
- {
- char buf[SSND_CHUNK_DATA];
- int i;
- align_long_t align_long;
-
- read(fd, buf, SSND_CHUNK_DATA);
-
- for (i=0; i<4; i++)
- {
- align_long.b[i] = buf[i];
- }
- ssnd_data->offset = align_long.l;
- for (i=0; i<4; i++)
- {
- align_long.b[i] = buf[i+4];
- }
- ssnd_data->blocksize = align_long.l;
- /*
- * store the offset to the beginning of the audio sample data so that
- * we can come back and play it later
- */
- ssnd_data->file_position = lseek(fd, 0, SEEK_CUR);
- ssnd_data->sample_area_bytes = chunk_header->size - 2*sizeof(long);
- if (chunk_header->size %2 == 1)
- {
- ssnd_data->sample_area_bytes++;
- }
-
- /*
- * move the fileptr to the end of the chunk
- */
- lseek(fd, ssnd_data->sample_area_bytes, SEEK_CUR);
- }
-
-
-
- /*
- * S K I P _ C H U N K
- */
- static void skip_chunk(
- int fd,
- chunk_header_t *chunk_header
- )
- {
- char id[5];
- int s;
-
- strncpy(id, chunk_header->id, 4);
- id[4] = '\0';
-
- /* skip the pad byte, if necessary */
- s = ((chunk_header->size % 2) == 1) ? chunk_header->size + 1 : chunk_header->size;
- lseek(fd, s, SEEK_CUR);
- }
-
-
-
-
- /*
- * C O N V E R T F R O M I E E E E X T E N D E D
- */
-
- /*
- * Copyright (C) 1988-1991 Apple Computer, Inc.
- * All rights reserved.
- *
- * Warranty Information
- * Even though Apple has reviewed this software, Apple makes no warranty
- * or representation, either express or implied, with respect to this
- * software, its quality, accuracy, merchantability, or fitness for a
- * particular purpose. As a result, this software is provided "as is,"
- * and you, its user, are assuming the entire risk as to its quality
- * and accuracy.
- *
- * This code may be used and freely distributed as long as it includes
- * this copyright notice and the above warranty information.
-
- * Machine-independent I/O routines for IEEE floating-point numbers.
- *
- * NaN's and infinities are converted to HUGE_VAL or HUGE, which
- * happens to be infinity on IEEE machines. Unfortunately, it is
- * impossible to preserve NaN's in a machine-independent way.
- * Infinities are, however, preserved on IEEE machines.
- *
- * These routines have been tested on the following machines:
- * Apple Macintosh, MPW 3.1 C compiler
- * Apple Macintosh, THINK C compiler
- * Silicon Graphics IRIS, MIPS compiler
- * Cray X/MP and Y/MP
- * Digital Equipment VAX
- *
- *
- * Implemented by Malcolm Slaney and Ken Turkowski.
- *
- * Malcolm Slaney contributions during 1988-1990 include big- and little-
- * endian file I/O, conversion to and from Motorola's extended 80-bit
- * floating-point format, and conversions to and from IEEE single-
- * precision floating-point format.
- *
- * In 1991, Ken Turkowski implemented the conversions to and from
- * IEEE double-precision format, added more precision to the extended
- * conversions, and accommodated conversions involving +/- infinity,
- * NaN's, and denormalized numbers.
- */
-
- # define UnsignedToFloat(u) \
- (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
-
- /****************************************************************
- * Extended precision IEEE floating-point conversion routine.
- ****************************************************************/
-
- static double ConvertFromIeeeExtended(
- char *bytes
- )
- {
- double f ;
- long expon ;
- unsigned long hiMant ;
- unsigned long loMant ;
-
- expon = ( ( bytes[0] & 0x7F ) << 8 ) | ( bytes[1] & 0xFF ) ;
- hiMant = ( (unsigned long)( bytes[2] & 0xFF ) << 24 )
- | ( (unsigned long)( bytes[3] & 0xFF ) << 16 )
- | ( (unsigned long)( bytes[4] & 0xFF ) << 8 )
- | ( (unsigned long)( bytes[5] & 0xFF ) ) ;
- loMant = ( (unsigned long)( bytes[6] & 0xFF ) << 24 )
- | ( (unsigned long)( bytes[7] & 0xFF ) << 16 )
- | ( (unsigned long)( bytes[8] & 0xFF ) << 8 )
- | ( (unsigned long)( bytes[9] & 0xFF ) ) ;
-
- if( expon == 0 && hiMant == 0 && loMant == 0 ) {
- f = 0;
- }
- else {
- if( expon == 0x7FFF ) { /* Infinity or NaN */
- f = HUGE_VAL;
- }
- else {
- expon -= 16383;
- f = ldexp( UnsignedToFloat( hiMant ), expon-=31 ) ;
- f += ldexp( UnsignedToFloat( loMant ), expon-=32 ) ;
- }
- }
-
- if( bytes[0] & 0x80 )
- return( -f ) ;
- else
- return( f ) ;
- }
-
-
-
- /*
- * I N I T _ A U D I O
- */
- static char *init_audio(
- int fd,
- audio_params_t *audio_params,
- ssnd_chunk_t *ssnd_data,
- comm_chunk_t *comm_data,
- long *size
- )
- {
- char *buf ;
- int bytes_read ;
-
- /*
- * decide what size blocks of samples we should read from the
- * AIFF file and pass to ALwritesamps
- */
- switch( audio_params->sampwidth ) {
- default :
- case AL_SAMPLE_8 :
- fprintf( stderr, "%s: sound file %s is not 16 bytes/sample\n",
- basename, filename ) ;
- return( NULL ) ;
- break ;
-
- case AL_SAMPLE_16 :
- bytes_per_samp = 2 ;
- break ;
- }
-
- switch( audio_params->nchannels ) {
- default :
- case AL_MONO :
- fprintf( stderr, "%s: sound file %s is not in stereo\n",
- basename, filename ) ;
- return( NULL ) ;
- break ;
-
- case AL_STEREO :
- samps_per_frame = 2 ;
- break ;
- }
-
- switch( audio_params->samprate ) {
- default :
- case AL_RATE_48000 :
- case AL_RATE_44100 :
- case AL_RATE_32000 :
- case AL_RATE_22050 :
- case AL_RATE_11025 :
- case AL_RATE_8000 :
- fprintf( stderr, "%s: sound file %s is not sampled at 16KHz\n",
- basename, filename ) ;
- return( NULL ) ;
- break ;
-
- case AL_RATE_16000 :
- frames_per_sec = 16000 ;
- break ;
- }
-
- *size = comm_data->nsampframes * samps_per_frame * bytes_per_samp ;
-
- buf = (char *)malloc( *size ) ;
- lseek( fd, ssnd_data->file_position, SEEK_SET ) ;
- if( ( bytes_read = read( fd, buf, *size ) ) < *size ) {
- fprintf( stderr, "%s: short read on %s\n", basename, filename ) ;
- *size = bytes_read ;
- }
-
- *size /= samps_per_frame ;
-
- return( buf ) ;
- }
-
-
-
- static int check_for_audio_hw( void )
- {
- int st = 0 ;
- inventory_t *base ;
- inventory_t *inv ;
-
- inv = base = getinvent() ;
- while( inv != NULL ) {
- /*
- * Ok if any type of audio hardware available.
- */
- #if defined( SVR3 )
- if( inv->class == INV_AUDIO ) {
- #else
- if( inv->inv_class == INV_AUDIO ) {
- #endif /* defined( SVR3 ) */
- st = 1 ;
- }
- inv = getinvent() ;
- }
-
- if( base )
- endinvent() ;
-
- return( st ) ;
- }
-
-
-
- int volume_change(
- int direction
- )
- {
- if( direction == 1 ) {
- if( gain_index <
- sizeof( gain_settings ) / sizeof( gain_settings[0] ) - 1 ) {
- gain_index++ ;
- }
- }
- else {
- if( gain_index > 0 ) {
- gain_index-- ;
- }
- }
- curr_left_gain = curr_right_gain = gain_settings[gain_index] ;
-
- set_gain( 1., 1. ) ;
-
- return( gain_index ) ;
- }
-
-
-
- static void set_gain_index(
- unsigned long gain
- )
- {
- int i ;
- long min = 256 ;
- long diff ;
-
- for( i = 0 ; i < sizeof( gain_settings ) / sizeof( gain_settings[0] ) ;
- i++ ) {
- diff = gain - gain_settings[i] ;
- if( diff < 0 )
- diff = -diff ;
- if( diff < min ) {
- min = diff ;
- gain_index = i ;
- }
- }
- }
-
-
-
- static void init_explosion_data(
- short *src_data,
- long src_size
- )
- {
- int d ;
- int a ;
- int i ;
- int st = 0 ;
- double angle ;
- double dist ;
- double s ;
- double x ;
- double y ;
- double l ;
- double r ;
-
- for( d = 0 ; d < MAX_EXP_DEPTH && !st ; d++ ) {
- for( a = 0 ; a < MAX_EXP_ANGLE && !st ; a++ ) {
- if( ( explosion_data[d][a] = (short *)malloc(
- ( src_size * 2 + 1 ) * sizeof( short ) ) ) == NULL ) {
- st = 1 ;
- }
- }
- }
-
- if( st ) {
- for( d = 0 ; d < MAX_EXP_DEPTH ; d++ ) {
- for( a = 0 ; a < MAX_EXP_ANGLE ; a++ ) {
- if( explosion_data[d][a] )
- free( explosion_data[d][a] ) ;
- }
- }
- explosion_size = 0 ;
- return ;
- }
-
- for( d = 0 ; d < MAX_EXP_DEPTH ; d++ ) {
- for( a = 0 ; a < MAX_EXP_ANGLE ; a++ ) {
- angle = a * EXP_DELTA_ANGLE ;
- dist = d * EXP_DELTA_DEPTH ;
- x = cos( angle ) ;
- s = 0.5 * ( x * ABS(x) ) ;
- dist = 1. - ( dist / 1250. ) ;
- dist *= dist ;
- r = sqrt( ( 0.5 - s ) * dist ) ;
- l = sqrt( ( 0.5 + s ) * dist ) ;
- for( i = 0 ; i < 2 * src_size ; i += 2 ) {
- explosion_data[d][a][i+0] = r * src_data[i+0] ;
- explosion_data[d][a][i+1] = l * src_data[i+1] ;
- }
- explosion_data[d][a][2*src_size] = 0 ;
- }
- }
- explosion_size = src_size ;
- }
-